﻿#include "OperGroup.h"

#include "GUIFrame/MainWindow.h"
#include "GUIWidget/ControlPanel.h"
#include "GUIWidget/TreeWidgetGroup.h"
#include "GUIFrame/CentralWidget.h"

#include "GUIDialog/GUIToolDialog/GUIGroupDialog.h"
#include "GUIWidget/TreeItemTypes.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsGroupData.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsGeometryData.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSEAModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractSEASubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractFESubSys.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSensors.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractJunction.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsPhysics.h"
#include "FITK_Component/FITKAcousticsPhysics/FITKAcousticsLoadManager.h"

#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsVirtualTopo.h"
#include "OperatorsInterface/GraphEventOperator.h"

#include <QTreeWidgetItem>
#include <QAction>
#include <QSet>

#define _DATAOBJTYPECOLUMN_ 0
#define _DATAOBJTYPE_ 3
#define _DATATYPECOLUMN_ 1
#define _DATATYPE_ 4
#define _DATAOBJIDCOLUMN_ 2
#define _DATAOBJID_ 5

namespace GUIOper
{
    bool OperGroup::execGUI()
    {
        //获取触发器
        if (!_emitter)return false;
        //获取动作名称
        QString name = _emitter->objectName();
        if (name == "actionCreateGroup")
            this->createGroupOper();
        else if (name == "actionGroupEdit")
            this->editOper();
        else if (name == "actionGroupShow")
            this->showOper();
        else if (name == "actionGroupHide")
            this->hideOper();
        else if (name == "actionGroupShowOnly")
            this->showOnlyOper();
        return true;
    }

    bool OperGroup::execProfession()
    {
        return true;
    }

    void OperGroup::updateGroupTreeSlot()
    {
        GUI::MainWindow* mw = GUI::MainWindow::GetMainWindowFromFramework();
        if (mw == nullptr ) return;
        GUI::CentralWidget* cw = mw->getCentralWidget();
        if (cw == nullptr) return;
        GUI::ControlPanel*  cp = cw->getControlPanel();
        if (cp == nullptr) return;
        GUI::TreeWidgetGroup* modelTree = dynamic_cast<GUI::TreeWidgetGroup*>(cp->getTreeWidget(GUI::TreeWidgetType::PageGroup));
        if (modelTree == nullptr) return;
        modelTree->updateGroupTree();
    }

    void OperGroup::updateGroupTreeState()
    {
        GUI::MainWindow* mw = GUI::MainWindow::GetMainWindowFromFramework();
        if (mw == nullptr) return;
        GUI::CentralWidget* cw = mw->getCentralWidget();
        if (cw == nullptr) return;
        GUI::ControlPanel*  cp = cw->getControlPanel();
        if (cp == nullptr) return;
        GUI::TreeWidgetGroup* modelTree = dynamic_cast<GUI::TreeWidgetGroup*>(cp->getTreeWidget(GUI::TreeWidgetType::PageGroup));
        if (modelTree == nullptr) return;
        modelTree->updateGroupTreeItemState();
    }

    void OperGroup::createGroupOper()
    {
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        GUI::GUIGroupDialog* groupDialog = new GUI::GUIGroupDialog(this, mainWindow);
        connect(groupDialog, SIGNAL(accepted()), this, SLOT(updateGroupTreeSlot()));
        groupDialog->show();
    }

    void OperGroup::editOper()
    {
        //获取编辑类型
        int objID = 0;
        int objType = Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsNone;
        void* pItem = nullptr;
        this->argValue<int>("ObjID", objID);
        this->argValue<void*>("SelectedItems", pItem);
        this->clearArgs();
        QList<QTreeWidgetItem*>* itemsList = (QList<QTreeWidgetItem*>*)(pItem);
        if (itemsList && !itemsList->isEmpty())
        {
            QTreeWidgetItem* item = itemsList->at(0);
            if (!item) return;
            if (item->type() == GUI::GroupTreeItemsType::GTGroup)
            {
                objID = item->data(_DATAOBJIDCOLUMN_, _DATAOBJID_).toInt();
            }
            else if (item->type() == GUI::GroupTreeItemsType::GTGroupChild)
            {
                objID = item->data(_DATAOBJIDCOLUMN_, _DATAOBJID_).toInt();
                objType = Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType(item->data(_DATAOBJTYPECOLUMN_, _DATAOBJTYPE_).toInt());
            }
        }
        if (objID == 0) return;
        //操作器
        QString emitterName;
        if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsNone)
            //编辑分组操作
            this->editGroupOper(objID);
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsGeometry)
            //编辑几何数据
            emitterName = "";
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsSEASubsystem)
            //编辑SEA子系统
            emitterName = "actionEditSEASubsystem";
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsFESubsystem)
            //编辑FE子系统
            emitterName = "actionEditFESubsystem";
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsSensors)
            //编辑FE传感器
            emitterName = "actionEditFESensor";
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsJunction)
            //编辑连接
            emitterName = "";
        else if (objType == Acoustics::FITKAcousticsGroupData::AcousticsGroupDataType::AcousticsLoad)
            //编辑载荷
            emitterName = "actionEditLoad";
        Core::FITKActionOperator* oper = FITKOPERREPO->getOperatorT<Core::FITKActionOperator>(emitterName);
        if (!oper) return;
        QAction* actTemp = new QAction;
        actTemp->setObjectName(emitterName);
        oper->setArgs("DataID", objID);
        oper->setEmitter(actTemp);
        oper->actionTriggered();
        delete actTemp;
    }

    void OperGroup::editGroupOper(int groupObjID)
    {
        //编辑分组数据操作API
        GUI::MainWindow * mainWindow = dynamic_cast<GUI::MainWindow *>(FITKAPP->getGlobalData()->getMainWindow());
        GUI::GUIGroupDialog* groupDialog = new GUI::GUIGroupDialog(this, groupObjID,mainWindow);
        connect(groupDialog, SIGNAL(accepted()), this, SLOT(updateGroupTreeSlot()));
        groupDialog->show();
    }

    void OperGroup::showOper()
    {
        //显示
        void* pItem = nullptr;
        this->argValue<void*>("SelectedItems", pItem);
        this->clearArgs();
        //获取数据
        bool isRoot = false;
        QList<int> groupObjID;
        QList<int> objIDList;
        QList<QTreeWidgetItem*>* itemsList = (QList<QTreeWidgetItem*>*)(pItem);
        QList<Acoustics::FITKAcousticsGroupData::AcousticsGroupData> objList;
        for (int i = 0; i < itemsList->size(); ++i)
        {
            QTreeWidgetItem* item = itemsList->at(0);
            if (!item) return;
            int objID = item->data(_DATAOBJIDCOLUMN_, _DATAOBJID_).toInt();
            if (item->type() == GUI::GroupTreeItemsType::GTGroupRoot)
            {
                isRoot = true;
                break;
            }
            else if (item->type() == GUI::GroupTreeItemsType::GTGroup && !groupObjID.contains(objID))
                groupObjID.append(objID);
            else if (item->type() == GUI::GroupTreeItemsType::GTGroupChild && !objIDList.contains(objID))
                objIDList.append(objID);
        }
        //更新分组的状态和选取数据
        this->updateGroupState(groupObjID, objIDList, isRoot, true);
        this->setObjShowOrHide(objIDList, 1);
        this->updateGroupTreeState();
    }

    void OperGroup::hideOper()
    {
        //隐藏
        void* pItem = nullptr;
        this->argValue<void*>("SelectedItems", pItem);
        this->clearArgs();
        //获取数据
        bool isRoot = false;
        QList<int> groupObjID;
        QList<int> objIDList;
        QList<QTreeWidgetItem*>* itemsList = (QList<QTreeWidgetItem*>*)(pItem);
        QList<Acoustics::FITKAcousticsGroupData::AcousticsGroupData> objList;
        for (int i = 0; i < itemsList->size(); ++i)
        {
            QTreeWidgetItem* item = itemsList->at(0);
            if (!item) return;
            int objID = item->data(_DATAOBJIDCOLUMN_, _DATAOBJID_).toInt();
            if (item->type() == GUI::GroupTreeItemsType::GTGroupRoot)
            {
                isRoot = true;
                break;
            }
            else if (item->type() == GUI::GroupTreeItemsType::GTGroup && !groupObjID.contains(objID))
                groupObjID.append(objID);
            else if (item->type() == GUI::GroupTreeItemsType::GTGroupChild && !objIDList.contains(objID))
                objIDList.append(objID);
        }
        //更新分组的状态和选取数据
        this->updateGroupState(groupObjID, objIDList, isRoot, false);
        this->setObjShowOrHide(objIDList, 2);
        this->updateGroupTreeState();
    }

    void OperGroup::showOnlyOper()
    {
        //仅显示
        void* pItem = nullptr;
        this->argValue<void*>("SelectedItems", pItem);
        this->clearArgs();
        //获取数据
        bool isRoot = false;
        QList<int> groupObjID;
        QList<int> objIDList;
        QList<QTreeWidgetItem*>* itemsList = (QList<QTreeWidgetItem*>*)(pItem);
        QList<Acoustics::FITKAcousticsGroupData::AcousticsGroupData> objList;
        for (int i = 0; i < itemsList->size(); ++i)
        {
            QTreeWidgetItem* item = itemsList->at(0);
            if (!item) return;
            int objID = item->data(_DATAOBJIDCOLUMN_, _DATAOBJID_).toInt();
            if (item->type() == GUI::GroupTreeItemsType::GTGroupRoot)
            {
                isRoot = true;
                break;
            }
            else if (item->type() == GUI::GroupTreeItemsType::GTGroup && !groupObjID.contains(objID))
                groupObjID.append(objID);
            else if (item->type() == GUI::GroupTreeItemsType::GTGroupChild && !objIDList.contains(objID))
                objIDList.append(objID);
        }
        //更新分组的状态和选取数据
        this->updateGroupState(groupObjID, objIDList, isRoot, true);
        this->setObjShowOrHide(objIDList, 3);
        this->updateGroupTreeState();
    }

    void OperGroup::updateGroupState(QList<int> groupIDList, QList<int>& objIDList, bool isRoot, bool state)
    {
        Acoustics::FITKAcousticsGroupManager* groupManager = Acoustics::FITKAcousticsGroupManager::GetGroupManagerFromFrame();
        if (!groupManager) return;
        int count = groupManager->getDataCount();
        if (isRoot)
        {
            //设置全部状态
            groupManager->enable(state);
            objIDList.clear();
            for (int i = 0; i < count; ++i)
            {
                Acoustics::FITKAcousticsGroupData* group = groupManager->getDataByIndex(i);
                if (!group) continue;
                group->enable(state);
                objIDList.append(group->getAllObjID());
            }
            return;
        }
        //获取操作数据对象ID
        QSet<int> objIDListSet = objIDList.toSet();
        for (int i = 0; i < count; ++i)
        {
            Acoustics::FITKAcousticsGroupData* group = groupManager->getDataByIndex(i);
            if (!group) continue;
            int groupID = group->getDataObjectID();
            QSet<int> objIDs = group->getAllObjID().toSet();
            if (!groupIDList.contains(groupID)) continue;
            group->enable(state);
            objIDListSet.unite(objIDs);
        }
        objIDList = objIDListSet.toList();
        //设置Group的状态
    }

    void OperGroup::setObjShowOrHide(QList<int> objList, int type)
    {
        bool state = true;
        bool isShow = false;
        if (type == 2)
            state = false;
        else if (type == 3)
            isShow = true;
        //获取渲染器
        EventOper::GraphEventOperator* operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("GraphPreprocess");
        if (!operGraph) return;
        //获取数据管理器
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        Acoustics::FITKAcousticsPhysics* physicsData = FITKAPP->getGlobalData()->getPhysicsData<Acoustics::FITKAcousticsPhysics>();
        if (!discModel || !discModel->getFEModel() || !discModel->getSEAModel() || !physicsData)return;
        Acoustics::FITKAcousticsSEASubSysManager* subsysSEAManager = discModel->getSEAModel()->getSEASubSysManager();
        Acoustics::FITKAcousticsFESubSysManager* subsysFEManager = discModel->getFEModel()->getFESubSysManager();
        Acoustics::FITKAcousticsSensorsManager* sensorManager = discModel->getFEModel()->getSensorManager();
        Acoustics::FITKJunctionManager* junctionManager = discModel->getJunctionManager();
        Acoustics::FITKAcousticsLoadManager* loadManager = physicsData->getFITKAcousticsLoadManager();
        if (!subsysSEAManager || !subsysFEManager || !sensorManager || !junctionManager || !loadManager)return;
        //几何
        QList<Interface::FITKAbsVirtualTopo*> virTopoList = getAllGeometryVirTopos();
        for (Interface::FITKAbsVirtualTopo* virTopo : virTopoList) {
            if (!virTopo) continue;
            if (objList.contains(virTopo->getDataObjectID()))
                virTopo->enable(state);
            else if (isShow)
                virTopo->enable(false);
        }
        //SEA子系统
        for (int i = 0; i < subsysSEAManager->getDataCount(); i++) {
            Acoustics::FITKAbstractSEASubSys* subSys = subsysSEAManager->getDataByIndex(i);
            if (!subSys)continue;
            if (objList.contains(subSys->getDataObjectID()))
                subSys->enable(state);
            else if (isShow)
                subSys->enable(false);
        }
        //FE子系统
        for (int i = 0; i < subsysFEManager->getDataCount(); i++) {
            Acoustics::FITKAbstractFESubSys* subSys = subsysFEManager->getDataByIndex(i);
            if (!subSys)continue;
            if (objList.contains(subSys->getDataObjectID()))
                subSys->enable(state);
            else if (isShow)
                subSys->enable(false);
        }
        //传感器
        for (int i = 0; i < sensorManager->getDataCount(); i++) {
            Acoustics::FITKAcousticsSensors* sensor = sensorManager->getDataByIndex(i);
            if (!sensor)continue;
            if (objList.contains(sensor->getDataObjectID()))
                sensor->enable(state);
            else if (isShow)
                sensor->enable(false);
        }
        //junction
        for (int i = 0; i < junctionManager->getDataCount(); i++) {
            Acoustics::FITKAbstractJunction* junction = junctionManager->getDataByIndex(i);
            if (!junction)continue;
            if (objList.contains(junction->getDataObjectID()))
                junction->enable(state);
            else if (isShow)
                junction->enable(false);
        }
        //载荷
        for (int i = 0; i < loadManager->getDataCount(); i++) {
            Acoustics::FITKAcousticsAbstractLoad* load = loadManager->getDataByIndex(i);
            if (!load)continue;
            if (objList.contains(load->getDataObjectID()))
                load->enable(state);
            else if (isShow)
                load->enable(false);
        }
        //更新显示或隐藏
        operGraph->updateAllVisibility();
    }

    QList<Interface::FITKAbsVirtualTopo*> OperGroup::getAllGeometryVirTopos()
    {
        QList<Interface::FITKAbsVirtualTopo*> virTopoList = {};
        Acoustics::FITKAcousticsGeometryData* geometryData = FITKAPP->getGlobalData()->getGeometryData<Acoustics::FITKAcousticsGeometryData>();
        if (geometryData == nullptr) {
            return virTopoList;
        }

        //获取所有的集合命令
        QList<Interface::FITKAbsGeoCommand*> allGeo = {};
        const int n = geometryData->getDataCount();
        for (int i = 0; i < n; ++i) {
            Interface::FITKAbsGeoCommand* geo = geometryData->getDataByIndex(i);
            if (geo == nullptr) {
                continue;
            }
            allGeo.append(geo);
        }

        //获取所有点、线、面的虚拓扑
        for (Interface::FITKAbsGeoCommand* geoCom : allGeo) {
            if (geoCom == nullptr) {
                continue;
            }
            Interface::FITKShapeVirtualTopoManager* virTopoPointManager = geoCom->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSPoint);
            if (virTopoPointManager != nullptr) {
                for (int i = 0; i < virTopoPointManager->getDataCount(); i++) {
                    virTopoList.append(virTopoPointManager->getDataByIndex(i));
                }
            }
            Interface::FITKShapeVirtualTopoManager* virTopoEdgeManager = geoCom->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSEdge);
            if (virTopoEdgeManager != nullptr) {
                for (int i = 0; i < virTopoEdgeManager->getDataCount(); i++) {
                    virTopoList.append(virTopoEdgeManager->getDataByIndex(i));
                }
            }
            Interface::FITKShapeVirtualTopoManager* virTopoFaceManager = geoCom->getShapeVirtualTopoManager(Interface::FITKGeoEnum::VTopoShapeType::VSFace);
            if (virTopoFaceManager != nullptr) {
                for (int i = 0; i < virTopoFaceManager->getDataCount(); i++) {
                    virTopoList.append(virTopoFaceManager->getDataByIndex(i));
                }
            }
        }
        return virTopoList;
    }
}
